Since commit
df1404650ccb ("mac80211: remove support for IFF_PROMISC")
monitor mode for rt2x00 has been made effectively useless because the
hardware filter is configured to drop packets whose intended recipient is
not the device, regardless of the presence of monitor mode interfaces.
This patch fixes this regression by adding explicit monitor mode support,
and by configuring the hardware filter accordingly.
Signed-off-by: Eli Cooper <elicooper@gmx.com>
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 4.3: adjust filenames]
Gbp-Pq: Topic bugfix/all
Gbp-Pq: Name rt2x00-fix-monitor-mode-regression.patch
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(®, RXCSR0_DROP_MCAST,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
- rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1);
rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR,
!(filter_flags & FIF_PLCPFAIL));
- rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1);
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST,
CONFIG_POWERSAVING,
CONFIG_HT_DISABLED,
CONFIG_QOS_DISABLED,
+ CONFIG_MONITORING,
/*
* Mark we currently are sequentially reading TX_STA_FIFO register
else
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+ if (conf->flags & IEEE80211_CONF_MONITOR)
+ set_bit(CONFIG_MONITORING, &rt2x00dev->flags);
+ else
+ clear_bit(CONFIG_MONITORING, &rt2x00dev->flags);
+
rt2x00dev->curr_band = conf->chandef.chan->band;
rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
rt2x00dev->tx_power = conf->power_level;
*total_flags |= FIF_PSPOLL;
}
- /*
- * Check if there is any work left for us.
- */
- if (rt2x00dev->packet_filter == *total_flags)
- return;
rt2x00dev->packet_filter = *total_flags;
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,